﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using ArduinoCommunication;
using CubeSolver;
using ImageAnalysis;
using RubikCube;
using NXTRobotController;

namespace RubikCubeSolver
{
    public partial class frmMain : Form
    {
        #region Fields

        private ColorFilterDialog clFilterDiag = new ColorFilterDialog();

        private VisualCubeFace face = new VisualCubeFace();

        private VisualCube cube = new VisualCube();

        private bool lockImage = false;

        private bool useLEGO = false;

        private NXTRobotController.frmLEGORobotSettings form;

        private NXTRobotController.LEGORobotControl robotControl;

        private string response = "";

        #endregion

        #region Props

        /// <summary>
        /// Face found in the image source
        /// </summary>
        public VisualCubeFace CurrentFace
        {
            get { return this.face; }
            set { this.face = value; }
        }

        /// <summary>
        /// The current cube
        /// </summary>
        public VisualCube CurrentCube
        {
            get { return this.cube; }
            set { this.cube = value; }
        }

        /// <summary>
        /// Locks the stored image
        /// </summary>
        public bool LockImage
        {
            get { return this.lockImage; }
            set { this.lockImage = value; }
        }

        #endregion

        #region Enums

        private enum Tabs
        {
            Main = 0,
            Analysis = 1,
            Movements = 2
        }

        #endregion

        #region Constructors

        public frmMain()
        {
            InitializeComponent();
        }

        #endregion

        #region Methods

        #region Kociemba Rubik Solver Methods

        [DllImport("KociembaRubikSolver.dll", EntryPoint = "SolveRubikCube")]
        public static extern unsafe IntPtr SolveRubikCube(void* cubeAsString);

        public static unsafe string SolveRubikCube(string cubeAsString)
        {
            IntPtr filePtr = IntPtr.Zero;
            try
            {
                filePtr = Marshal.StringToHGlobalAnsi(cubeAsString);
                IntPtr t = SolveRubikCube(filePtr.ToPointer());
                return Marshal.PtrToStringAnsi(t); ;
            }
            finally
            {
                if (filePtr != IntPtr.Zero)
                    Marshal.FreeHGlobal(filePtr);
            }
        }

        #endregion

        private void ResolveCube()
        {
            //INÍCIO
            RobotCubeSolver cubeSolver = new RobotCubeSolver();

            // analisa as faces do cubo, enviando comandos a Arduino para mover o cubo e descobrir todas as faces
            if (this.useLEGO)
            {
                StoredData.Cubo = CubeAnalyser.AnalyseCubeLEGO(StoredData.GetAllFilters(), 10, 10, robotControl);
            }
            else
            {
                // aqui entra o programa principal
                StoredData.Cubo = CubeAnalyser.AnalyseCube(StoredData.GetAllFilters(), 10, 10, arduinoChannel);
            }

            if (StoredData.Cubo == null)
                return;

            if (!this.useLEGO)
            {
                // resolve o cubo, obtendo uma lista de movimentos a ser enviado a Arduino
                List<Movement> movementsToSolve = cubeSolver.Solve(StoredData.Cubo);
                // envia movimentos a Arduino
                arduinoChannel.SendInitExecution();
                arduinoChannel.SendMovements(movementsToSolve);
                arduinoChannel.SendFinishExecution();
            }
            else
            {
                string cubo = string.Empty;
                Invoke((MethodInvoker)delegate
                {
                    cubo = textBox1.Text;
                });
                List<LEGOAction> actions = new List<LEGOAction>();
                try
                {
                    actions = cubeSolver.SolveLEGO(StoredData.Cubo);
                }
                catch (Exception exc)
                {
                    MessageBox.Show(exc.Message);
                    Invoke((MethodInvoker)delegate
                    {
                        this.startButton.Enabled = true;
                        this.stopButton.Enabled = false;
                    });
                    return;
                }
                robotControl.DoInitializationMovement();
                foreach (LEGOAction item in actions)
                {
                    robotControl.DoAction(item);
                }
                Invoke((MethodInvoker)delegate
                {
                    this.startButton.Enabled = true;
                    this.stopButton.Enabled = false;
                });
            }
        }

        private void ResolveCubeLEGO()
        {
            RobotCubeSolver cubeSolver = new RobotCubeSolver();
            string cubo = string.Empty;
            Invoke((MethodInvoker)delegate
            {
                cubo = textBox1.Text;
            });
            List<LEGOAction> actions = new List<LEGOAction>();
            try
            {
                actions = cubeSolver.SolveLEGO(StoredData.Cubo);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                return;
            }
            foreach (LEGOAction item in actions)
            {
                robotControl.DoAction(item);
            }
        }

        private void ClearVisualCube()
        {
            pnlUpLeft.BackColor = Color.Black;

            pnlUpMid.BackColor = Color.Black;

            pnlUpRight.BackColor = Color.Black;

            pnlMidLeft.BackColor = Color.Black;

            pnlCenter.BackColor = Color.Black;

            pnlMidRight.BackColor = Color.Black;

            pnlDownLeft.BackColor = Color.Black;

            pnlDownMid.BackColor = Color.Black;

            pnlDownRight.BackColor = Color.Black;

        }

        /// <summary>
        /// Draw the rectangles in image
        /// </summary>
        /// <param name="picBox"></param>
        /// <param name="smp"></param>
        private void DrawRectangles(ref PictureBox picBox, ImageSample smp)
        {
            Graphics g = picBox.CreateGraphics();
            Pen p = new Pen(Brushes.Black, 2);
            lblFaceletsDetected.Text = smp.RealFacelets.Keys.Count.ToString();
            int count = 0;
            ClearVisualCube();
            foreach (Rectangle rect in smp.RealFacelets.Keys)
            {
                p.Color = smp.RealFacelets[rect];
                g.DrawRectangle(p, rect);
                if (smp.Cores.Count > count)
                {
                    switch (count)
                    {
                        case 0:
                            pnlUpLeft.BackColor = smp.Cores[count];
                            break;
                        case 1:
                            pnlUpMid.BackColor = smp.Cores[count];
                            break;
                        case 2:
                            pnlUpRight.BackColor = smp.Cores[count];
                            break;
                        case 3:
                            pnlMidLeft.BackColor = smp.Cores[count];
                            break;
                        case 4:
                            pnlCenter.BackColor = smp.Cores[count];
                            break;
                        case 5:
                            pnlMidRight.BackColor = smp.Cores[count];
                            break;
                        case 6:
                            pnlDownLeft.BackColor = smp.Cores[count];
                            break;
                        case 7:
                            pnlDownMid.BackColor = smp.Cores[count];
                            break;
                        case 8:
                            pnlDownRight.BackColor = smp.Cores[count];
                            break;
                        default:
                            break;
                    }
                }
                count++;
            }
        }

        /// <summary>
        /// Filter especific image.
        /// </summary>
        /// <param name="picBox">Picturebox to show the filtered image</param>
        private void FilterImage(ref PictureBox picBox)
        {
            if (picbVideoCapture.Image != null)
            {
                ImageSample smp = new ImageSample();
                smp.SampleImg = CubeAnalyser.SourceImage;

                ImageAnalyser analyser = new ImageAnalyser();
                analyser.Sample = smp;
                analyser.Filters = new List<ColorFilter>();
                analyser.Filters.Add(StoredData.GetFilter(picBox.Name));

                ManualResetEvent mre = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(analyser.FilterColors, mre);

                WaitHandle hdl = (WaitHandle)mre;
                hdl.WaitOne();

                picBox.Image = analyser.Sample.SampleImg;
            }
        }

        private void IdentifyColorsMainImage()
        {
            if (picbVideoCapture.Image != null)
            {
                LockImage = true;
                ImageSample smp = new ImageSample();
                smp.SampleImg = picbVideoCapture.Image;
                smp.FaceletMinHeight = (int)numMinHeight.Value;
                smp.FaceletMinWidth = (int)numMinHeight.Value;

                ImageAnalyser analyser = new ImageAnalyser();
                analyser.Sample = smp;
                analyser.Filters = StoredData.GetAllFilters();

                ManualResetEvent mre = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(analyser.AnalyseImageSample, mre);

                WaitHandle hdl = (WaitHandle)mre;
                hdl.WaitOne();

                DrawRectangles(ref picbVideoCapture, analyser.Sample);
                FillPictureBoxWithSample(analyser.Sample);
                LockImage = false;
            }
        }

        private void FillPictureBoxWithSample(ImageSample smp)
        {
            foreach (Control item in groupImgProc.Controls)
            {
                if (item is PictureBox)
                {
                    if (smp.FilteredImages.ContainsKey(item.Name))
                        ((PictureBox)item).Image = smp.FilteredImages[item.Name];
                }
            }
        }

        /// <summary>
        /// Links the radiobutton objects to the respective picturebox
        /// </summary>
        private void LinkRadioToPicture()
        {
            //Link between radiobuttons and picturebox
            radColor1.Tag = picbRedFilter;
            radColor2.Tag = picbBlueFilter;
            radColor3.Tag = picbGreenFilter;
            radColor4.Tag = picbYellowFilter;
            radColor5.Tag = picbOrangeFilter;
            radColor6.Tag = picbWhiteFilter;
        }

        /// <summary>
        /// Links the picturebox objects to the respectives color filters
        /// </summary>
        private void LinkPictureToFilter()
        {
            foreach (Control item in groupImgProc.Controls)
            {
                if (item is PictureBox)
                {
                    ColorFilter newFilter = new ColorFilter();
                    newFilter.FilterID = item.Name;
                    if (item.Name.Contains("Red"))
                        newFilter.BorderColor = Color.Red;
                    else if (item.Name.Contains("Blue"))
                        newFilter.BorderColor = Color.Blue;
                    else if (item.Name.Contains("Green"))
                        newFilter.BorderColor = Color.Green;
                    else if (item.Name.Contains("Yellow"))
                        newFilter.BorderColor = Color.Yellow;
                    else if (item.Name.Contains("Orange"))
                        newFilter.BorderColor = Color.Orange;
                    else
                        newFilter.BorderColor = Color.White;
                    StoredData.AddFilter(newFilter);
                }
            }
        }

        /// <summary>
        /// Save the filter settings.
        /// </summary>
        private void SaveFilterSettings()
        {
            SaveFileDialog diag = new SaveFileDialog();
            diag.Filter = "Settings save file | *.sav";
            if (diag.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                StoredData.SaveFilter(diag.FileName);
        }

        /// <summary>
        /// Load filter settings from XML.
        /// </summary>
        private void LoadFilterSettings()
        {
            OpenFileDialog diag = new OpenFileDialog();
            diag.Filter = "Settings save file|*.sav";
            if (diag.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                StoredData.LoadFiltersFromXml(diag.FileName);
        }

        /// <summary>
        /// Gets the selected radiobutton of the ImageProcessing GroupBox
        /// </summary>
        /// <returns>Returns the control</returns>
        private Control GetSelectedRadioButton()
        {
            Control ctrl = new Control();
            foreach (Control item in groupImgProc.Controls)
            {
                if (item is RadioButton && ((RadioButton)item).Checked)
                {
                    ctrl = item;
                    break;
                }
            }
            return ctrl;
        }

        /// <summary>
        /// Apply the filters configured in the Filter Settings Dialog
        /// </summary>
        private void ApplyFilterChanges()
        {
            Control radioBtn = GetSelectedRadioButton();
            Control pic = (Control)radioBtn.Tag;
            clFilterDiag.FilterSettings.FilterID = pic.Name;
            StoredData.AddFilter(clFilterDiag.FilterSettings);
        }

        /// <summary>
        /// Gets the the filter related to the selected radiobutton
        /// </summary>
        /// <returns>Returns the colorfilter.</returns>
        private ColorFilter GetCurrentFilter()
        {
            Control radioBtn = GetSelectedRadioButton();
            Control pic = (Control)radioBtn.Tag;
            return StoredData.GetFilter(pic.Name);
        }

        /// <summary>
        /// Configure the ColorFilterDialog
        /// </summary>
        private void SetColorFilterDialog()
        {
            clFilterDiag = new ColorFilterDialog();
            clFilterDiag.FilterSettings = GetCurrentFilter();
            clFilterDiag.FilterSettingsChanged += new ColorFilterDialog.FilterSettingsChangedHandler(ColorFilterDialog_FilterSettingsChanged);
        }

        /// <summary>
        /// Gets the active tab in tab control
        /// </summary>
        /// <returns></returns>
        private Tabs GetActiveTab()
        {
            switch (tabControl1.SelectedIndex)
            {
                case 1:
                    return Tabs.Analysis;
                case 2:
                    return Tabs.Movements;
                default:
                    return Tabs.Main;
            }
        }

        #endregion

        #region Events

        #region Source Menu Events

        private void btnStartCam_EnabledChanged(object sender, EventArgs e)
        {
            btnStopCam.Enabled = !btnStartCam.Enabled;
            btnVideoFormat.Enabled = btnStopCam.Enabled;
        }

        private void btnStartCam_Click(object sender, EventArgs e)
        {
            btnStartCam.Enabled = false;
            try
            {
                videoCaptureDevice1.NewStart();
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
                btnStartCam.Enabled = true;
            }
        }

        private void btnStopCam_Click(object sender, EventArgs e)
        {
            btnStartCam.Enabled = true;
            videoCaptureDevice1.NewStop();
        }

        private void btnLoadImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog diag = new OpenFileDialog();
            diag.Filter = "Image Files|*.BMP;*.JPG;*.GIF;*.PNG";
            if (diag.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                saveImageToolStripMenuItem.Enabled = true;
                CubeAnalyser.SourceImage = Image.FromFile(diag.FileName);
                if (GetActiveTab() == Tabs.Analysis)
                    picbVideoCapture.Image = (Image)CubeAnalyser.SourceImage.Clone();
                IdentifyColorsMainImage();
            }
        }

        private void saveImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog diag = new SaveFileDialog();
            diag.Filter = "Image Files|*.BMP;*.JPG;*.GIF;*.PNG";
            if (diag.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                CubeAnalyser.SourceImage.Save(diag.FileName);
        }

        private void videoFormatToolStripMenuItem_Click(object sender, EventArgs e)
        {
            videoCaptureDevice1.ShowVideoFormatDialog();
        }

        private void setValidBoundsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmImageBounds form = new frmImageBounds();
            form.ShowDialog(this);
        }

        #endregion

        #region General Forms Events

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (btnStopCam.Enabled)
                videoCaptureDevice1.NewStop();
            if (!clFilterDiag.IsDisposed)
            {
                clFilterDiag.Close();
            }
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            LinkRadioToPicture();
            LinkPictureToFilter();
            robotControl = new NXTRobotController.LEGORobotControl();
            form = new NXTRobotController.frmLEGORobotSettings(ref robotControl);
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (GetActiveTab() == Tabs.Analysis)
                tmrFilters.Enabled = btnStopFilterScan.Enabled;
            else
                tmrFilters.Enabled = false;
        }

        #endregion

        #region Color Filter Events

        private void ColorFilterDialog_FilterSettingsChanged(object sender, ColorFilterEventArgs e)
        {
            ApplyFilterChanges();
            //Control radio = GetSelectedRadioButton();
            //switch (e.ChangeType)
            //{
            //    case TypeFilterChanged.RGB:

            //        FilterImage(ref radio.Tag);
            //        break;
            //    case TypeFilterChanged.RectangleSize:
            //        picbVideoCapture.Image = (Image)CubeAnalyser.SourceImage.Clone();
            //        FindObjectsOfImage((PictureBox)radio.Tag);
            //        break;
            //    default:
            //        break;
            //}
        }

        private void btnConfigColorFilter_Click(object sender, EventArgs e)
        {
            SetColorFilterDialog();
            clFilterDiag.Show(this);
        }

        private void btnSaveSettings_Click(object sender, EventArgs e)
        {
            SaveFilterSettings();
        }

        private void btnLoadSettings_Click(object sender, EventArgs e)
        {
            LoadFilterSettings();
        }

        private void btnFilterImage_Click(object sender, EventArgs e)
        {
            IdentifyColorsMainImage();
        }

        private void btnFilterScan_EnabledChanged(object sender, EventArgs e)
        {
            btnStopFilterScan.Enabled = !btnFilterScan.Enabled;
        }

        private void btnStopFilterScan_Click(object sender, EventArgs e)
        {
            tmrFilters.Enabled = false;
            btnFilterScan.Enabled = true;
        }

        private void btnFilterScan_Click(object sender, EventArgs e)
        {
            tmrFilters.Enabled = true;
            btnFilterScan.Enabled = false;
        }

        private void tmrFilters_Tick(object sender, EventArgs e)
        {
            LockImage = true;
            tmrFilters.Enabled = false;
            IdentifyColorsMainImage();
            tmrFilters.Enabled = true;
            LockImage = false;
        }

        #endregion

        #region Movements Events

        private void Solve_Click(object sender, EventArgs e)
        {
            RobotCubeSolver solver = new RobotCubeSolver();
            List<Movement> movements = solver.Solve(textBox1.Text);
            movimentosText.Text = "";
            foreach (Movement movement in movements)
            {
                movimentosText.Text += movement.toString() + "\n";
            }
            movementsProtocol.Text = ArduinoProtocol.CreateBitRepresentationOfMovements(movements);
        }

        private void SolveWithArduino_Click(object sender, EventArgs e)
        {
            RobotCubeSolver solver = new RobotCubeSolver();
            List<Movement> movements = solver.Solve(textBox1.Text);
            movimentosText.Text = "";
            arduinoResponse.Text = "";
            foreach (Movement movement in movements)
            {
                movimentosText.Text += movement.toString() + "\n";
            }
            movementsProtocol.Text = ArduinoProtocol.CreateBitRepresentationOfMovements(movements);
            ArduinoChannel channel = new ArduinoChannel(portUsed.Text, ReceivedData);
            channel.SendInitExecution();
            channel.SendMovements(movements);
            channel.SendFinishExecution();
            Thread.Sleep(5000);
            arduinoResponse.Text += response;
        }

        #endregion

        private void videoCaptureDevice1_ImageCaptured(object source, VideoCapture.ImageCapturedEventArgs e)
        {
            if (!tmrFilters.Enabled || !lockImage)
            {
                lockImage = false;
                Image img = (Image)e.WebCamImage.Clone();
                CubeAnalyser.SourceImage = img;
                saveImageToolStripMenuItem.Enabled = true;
                if (GetActiveTab() == Tabs.Analysis)
                {
                    this.picbVideoCapture.Image = (Image)e.WebCamImage.Clone();
                }
            }
        }

        private void MainStart_Click(object sender, EventArgs e)
        {
            startButton.Enabled = false;
            startButton.BackColor = Color.Transparent;
            stopButton.Enabled = true;
            stopButton.BackColor = Color.Red;
            threadToResolveCube = new Thread(new ThreadStart(this.ResolveCube));
            threadToResolveCube.Start();
        }

        private void lEGOMindstormsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            form.ShowDialog(this);
            this.useLEGO = form.UsingLEGO;
        }

        // Trata dados recebidos do ArduinoChannel
        private void ReceivedData(object sender, ArduinoDataReceivedEventArgs e)
        {
            response += e.DataRead;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (arduinoChannel == null || !arduinoChannel.isPortOpen())
            {
                arduinoChannel = new ArduinoChannel(portUsed.Text, ReceivedData2);
                if (arduinoChannel.isPortOpen())
                {
                    labelConnected.Text = "Connected";
                    connectButton.BackColor = Color.Transparent;
                    startButton.BackColor = Color.Lime;
                }
                else
                {
                    labelConnected.Text = "Not Connected";
                    connectButton.BackColor = Color.Yellow;
                    startButton.BackColor = Color.Transparent;
                }
            }
        }

        // Trata dados recebidos do ArduinoChannel
        private void ReceivedData2(object sender, ArduinoDataReceivedEventArgs e)
        {
            byte b;
            for (int i = 0; i < e.NumBytesRead; i++)
            {
                b = e.DataRead[i];
                if (b == ArduinoProtocol.END_PROGRAM)
                {
                    // fim do programa
                    stopButton_Click_1(null, null);
                    return;
                }
            }
        }

        private void stopButton_Click_1(object sender, EventArgs e)
        {
            startButton.Enabled = true;
            startButton.BackColor = Color.Red;
            stopButton.Enabled = false;
            stopButton.BackColor = Color.Transparent;

            threadToResolveCube.Abort();
            threadToResolveCube.Join();
        }

        #endregion

        private void btnGetBlobs_Click(object sender, EventArgs e)
        {
            ColorFilter filter = new ColorFilter();
            filter.Red = new AForge.IntRange((int)nRedMin.Value, (int)nRedMax.Value);
            filter.Green = new AForge.IntRange((int)nGreenMin.Value, (int)nGreenMax.Value);
            filter.Blue = new AForge.IntRange((int)nBlueMin.Value, (int)nBlueMax.Value);

            ImageAnalyser imgAnalyser = new ImageAnalyser();
            List<Rectangle> recs = imgAnalyser.GetSquares(picbVideoCapture.Image, (int)numMinWidth.Value, (int)numMinHeight.Value, filter);

            if (recs.Count > 0)
            {
                picbVideoCapture.Refresh();
                Graphics g = picbVideoCapture.CreateGraphics();
                Pen p = new Pen(Brushes.DarkRed, 2.0F);
                g.DrawRectangles(p, recs.ToArray());
            }

        }

        private void btnStartManualRecognition_Click(object sender, EventArgs e)
        {
            btnFilterScan.Enabled = true;
            btnSetFaceRecognition.Enabled = true;
            cubeMap.Clear();
            CurrentF = 0;
            AskForFace();
        }

        private void ContextMenuStripItem_Click(object sender, EventArgs e)
        {
            Panel p = new Panel();
            foreach (Control item in pnlCubeDiagram.Controls)
            {
                if (item is Panel && item.Name == pnlName)
                {
                    p = (Panel)item;
                    break;
                }
            }
            string color = ((ToolStripItem)sender).Text;
            p.BackColor = Color.FromName(color);
        }

        private void pnlUpLeft_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                pnlName = ((Control)sender).Name;
            }
        }

        private void btnSetFaceRecognition_Click(object sender, EventArgs e)
        {
            Dictionary<CubeFaceletType, CubeFaceColor> lala = new Dictionary<CubeFaceletType, CubeFaceColor>();
            FillTmpFacelets(lala);
            AskNextFace(lala);
        }

        private CubeFaceColor GetCubeFaceColor(Color c)
        {
            switch (c.Name)
            {
                case "Red":
                    return CubeFaceColor.R;
                case "Green":
                    return CubeFaceColor.G;
                case "Yellow":
                    return CubeFaceColor.Y;
                case "Blue":
                    return CubeFaceColor.B;
                case "White":
                    return CubeFaceColor.W;
                case "Orange":
                    return CubeFaceColor.O;
                default:
                    break;
            }
            return CubeFaceColor.B;
        }

        private Color GetColorByCubeFaceColor(CubeFaceColor c)  
        {
            switch (c)
            {
                case CubeFaceColor.B:
                    return Color.Blue;
                case CubeFaceColor.Y:
                    return Color.Yellow;
                case CubeFaceColor.O:
                    return Color.Orange;
                case CubeFaceColor.W:
                    return Color.White;
                case CubeFaceColor.G:
                    return Color.Green;
                case CubeFaceColor.R:
                    return Color.Red;
                default:
                    return Color.Red;
            }
        }

        private void FillPanelCubeDiagram()
        {
            foreach (Panel item in pnlCubeDiagram.Controls)
            {
                CubeFaceletType cft;
                Enum.TryParse<CubeFaceletType>(item.Tag.ToString(), out cft);
                foreach (CubeFace k in StoredData.Cubo.CubeMap.Keys)
                {
                    if (StoredData.Cubo.CubeMap[k] == (CubeFaceType)CurrentF)
                    {
                        if(k.getFacelets().ContainsKey(cft))
                        {
                            item.BackColor = GetColorByCubeFaceColor(k.getFacelets()[cft]);
                        }
                    }
                }
            }
        }

        private void AskForFace()
        {
            switch ((CubeFaceType)CurrentF)
            {
                case CubeFaceType.L:
                    lblAskFace.Text = "Left...";
                    break;
                case CubeFaceType.F:
                    lblAskFace.Text = "Front...";
                    break;
                case CubeFaceType.R:
                    lblAskFace.Text = "Right...";
                    break;
                case CubeFaceType.B:
                    lblAskFace.Text = "Back...";
                    break;
                case CubeFaceType.D:
                    lblAskFace.Text = "Down...";
                    break;
                case CubeFaceType.U:
                    lblAskFace.Text = "Up...";
                    break;
                default:
                    break;
            }
            FillPanelCubeDiagram();
        }

        private void AskNextFace(Dictionary<CubeFaceletType, CubeFaceColor> tmpFacelets)
        {
            cubeMap.Add(new CubeFace(tmpFacelets), (CubeFaceType)CurrentF);
            CurrentF++;
            if (CurrentF == 6)
            {
                StoredData.Cubo = new Cube(cubeMap);
                lblAskFace.Text = "Done. Face F para a Camera e Face R para o NXT";
            }
            else
            {
                AskForFace();
            }
        }

        private void FillTmpFacelets(Dictionary<CubeFaceletType, CubeFaceColor> tmpFacelets)
        {
            foreach (Panel item in pnlCubeDiagram.Controls)
            {
                CubeFaceletType cft;
                Enum.TryParse<CubeFaceletType>(item.Tag.ToString(), out cft);
                tmpFacelets.Add(cft, GetCubeFaceColor(item.BackColor));
            }
        }

        Dictionary<CubeFace, CubeFaceType> cubeMap = new Dictionary<CubeFace, CubeFaceType>();
        //Dictionary<CubeFaceletType, CubeFaceColor> tmpFacelets = new Dictionary<CubeFaceletType, CubeFaceColor>();
        int CurrentF;
        private string pnlName = string.Empty;

        private void btnMainStartWthCam_Click(object sender, EventArgs e)
        {
            threadToResolveCube = new Thread(new ThreadStart(this.ResolveCubeLEGO));
            threadToResolveCube.Start();
        }
    }
}
